/*------------------------------------------------------------------------------
* GeoVISTA Center, Penn State Geography Deptartment*
* Copyright (c), 2002, GeoVISTA Center
* All Rights Researved.
*
* Original Authors: Frank Hardisty, Bonan Li
* $Author: bonan_li $
*
* $Date: 2004/03/03 19:03:11 $
*
* $Id: LayerLineExtension.java,v 1.4 2004/03/03 19:03:11 bonan_li Exp $
*
* To Do:
*
 ------------------------------------------------------------------------------*/

package edu.psu.geovista.app.map;

import edu.psu.geovista.symbollibrary.SymbolInterface;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Vector;



/**
 * put your documentation comment here
 */
public class LayerLineExtension extends LayerShapeExtension implements LayerInterface {

    private SymbolInterface[] symbols = null;

    public void setSymbols(SymbolInterface[] symbols) {
      this.symbols = symbols;
    }

    /**
  * put your documentation comment here
  * @param g2
  */
 public void render(Graphics2D g2) {
      if (this.objectColors == null) {
        System.out.println("LayerShape, render called on null objectColors");
        return;
      }
      if (g2 == null) {
        throw new IllegalArgumentException(this.toString() +
            " Null graphics passed in to render(Graphics2D).");
      }

      if (this.isAuxiliary) {
        System.out.println("rendering auxiliary layer....line. ");
        super.renderAux(g2);
        return;
      }

      for (int path = 0; path < spatialData.length; path++) {
        this.renderObservationNoIndication(path, g2);
      }
    } //end method


    public void renderObservation(int obs, Graphics2D g2) {
      if (obs < 0) {
        return;
      }
      if (this.objectColors.length <= obs) {
        return;
      }

      Shape shp = spatialData[obs];
      if (fisheyes != null) {
        shp = fisheyes.transform(shp);
      }

      g2.setStroke(this.defaultStroke);
      Color color = this.objectColors[obs];
      g2.setColor(color);
      g2.draw(shp);

      if (this.defaultStrokeWidth >= 0.1f) {
        g2.setColor(this.colorLine);
        g2.draw(shp);
      }

      //Here's the place drawing symbols.
      if (this.symbols != null ) {
        shp.getBounds2D().getCenterX();
        shp.getBounds2D().getCenterY();
        this.renderSymbol(this.symbols[obs], shp.getBounds2D().getCenterX(),
                          shp.getBounds2D().getCenterY(), g2);
      }

    }

    private void renderSymbol(SymbolInterface sym, double x, double y,
                              Graphics2D g2d) {
      if (this.symbols != null ||sym!= null) {
        sym.setX( (int) (x + 0.5));
        sym.setY( (int) (y + 0.5));
        sym.draw(g2d);
      }
    }

    public void renderObservationNoIndication(int obs, Graphics2D g2)
    {
      if (obs < 0) {
        return;
      }
      if (this.objectColors.length <= obs) {
        return;
      }
      Shape shp = spatialData[obs];
      if (fisheyes != null) {
        shp = fisheyes.transform(shp);
      }

      if (conditionArray[obs] > -1) {
        g2.setStroke(this.defaultStroke);
        if(!this.selOriginalColorMode || this.selectedObservationsFullIndex[obs] == this.STATUS_SELECTED ||!this.selectionExists){
          Color color = this.objectColors[obs];
          g2.setColor(color);
          g2.draw(shp);
        }

        if (this.defaultStrokeWidth >= 0.1f) {
          g2.setColor(this.colorLine);
          g2.draw(shp);
        }

        if (this.selOriginalColorMode) {
          if (this.selectedObservationsFullIndex[obs] == this.STATUS_NOT_SELECTED &&
              this.selectionExists) {
            g2.setPaint(this.selectionTexture);
            g2.draw(shp);
          }
        }
        else if (!this.selOriginalColorMode) {
          if (this.selectedObservationsFullIndex[obs] == this.STATUS_SELECTED) {
            g2.setPaint(this.selectionTexture);
            g2.draw(shp);
          }
        }
      }

      //Here's the place drawing symbols.
      if (this.symbols != null ) {
        shp.getBounds2D().getCenterX();
        shp.getBounds2D().getCenterY();
        this.renderSymbol(this.symbols[obs], shp.getBounds2D().getCenterX(),
                          shp.getBounds2D().getCenterY(), g2);
      }
    }

    /**
     * SelectionX1 is expected to be less than selectionX2, same with Y1 and y2.
     * Selected observations should be rendered with the color "colorSelection".
     *
     * selectionX1 is expected to be less than selectionX2, same with Y1 and y2
     */
    public void findSelection(int selectionX1, int selectionX2, int selectionY1,
                              int selectionY2) {
      Rectangle selBox = new Rectangle(selectionX1, selectionY1,
                                       selectionX2 - selectionX1,
                                       selectionY2 - selectionY1);

      Vector selObs = new Vector();
      for (int i = 0; i < this.spatialData.length; i++) {
        Rectangle shpBox = this.spatialData[i].getBounds();
        Rectangle2D r2 = null;
        if (selBox.intersects(shpBox)) {
          if (this.spatialData[i].contains(selBox) ||
              this.spatialData[i].intersects(selBox)) {
            selObs.add(new Integer(i));
          } //end if really intersects
        } //end if rough intersects
      } //next
      this.selectedObservations = new int[selObs.size()];
      int j = 0;
      for (Enumeration e = selObs.elements(); e.hasMoreElements(); ) {
        Integer anInt = (Integer) e.nextElement();
        this.selectedObservations[j] = anInt.intValue();
        j++;
      }
    }

    /*
     * selectionX1 is expected to be less than selectionX2, same with Y1 and y2
     */
    public void findSelectionShift(int selectionX1, int selectionX2,
                                   int selectionY1,
                                   int selectionY2) {
      Rectangle selBox = new Rectangle(selectionX1, selectionY1,
                                       selectionX2 - selectionX1,
                                       selectionY2 - selectionY1);

      Vector selObs = new Vector();
      Arrays.sort(this.selectedObservations); //have to do this for the searching
      for (int i = 0; i < this.spatialData.length; i++) {
        Rectangle shpBox = this.spatialData[i].getBounds();
        if (selBox.intersects(shpBox)) {
          if (Arrays.binarySearch(this.selectedObservations, i) < 0) {
            selObs.add(new Integer(i));
          }
        }
      }
      int[] selectedObserCp = new int[this.selectedObservations.length];
      selectedObserCp = (int[]) (this.selectedObservations.clone());
      this.selectedObservations = new int[selectedObserCp.length + selObs.size()];
      int j = 0;
      for (j = 0; j < selectedObserCp.length; j++) {
        this.selectedObservations[j] = selectedObserCp[j];
      }
      for (Enumeration e = selObs.elements(); e.hasMoreElements(); ) {
        Integer anInt = (Integer) e.nextElement();
        this.selectedObservations[j] = anInt.intValue();
        j++;
      }

    }

    public int findIndication(int x, int y) {
      for (int i = 0; i < this.spatialData.length; i++) {
        Rectangle shpBox = this.spatialData[i].getBounds();
        Rectangle2D r2 = null;
        if (shpBox.contains(x, y)) {
          if (this.spatialData[i].contains(x, y)) {
            return i;

          } //end if really intersects
        } //end if rough intersects
      } //next
      //couldn't find anything, so
      return Integer.MIN_VALUE;
    }
}